assume cs:code,ds:data

data segment
    count        DW        256        dup(0)
    count4Number        DW  0
    count4Uletter        DW  0
    count4Lletter   DW  0
    count4Other                DW        0

    msg db 'please input the string: $'
    msg1 db "number count:",36
    msg2 db "upcase letter count:",36
    msg3 db "lowcase letter count:",36
    msg4 db "other character count:",36
    msg5 db "  times appeared character:",36
data ends

code segment
Break        MACRO
    NOP
    INT        1H
    NOP
ENDM

EnterLine        MACRO
    MOV                AH,02
    MOV                DL,0AH
    INT                21H
    MOV                DL,0DH
    INT                21H
ENDM

PushAll        MACRO
    PUSH        SI
    PUSH    DI
    PUSH    BX
    PUSH    CX
    PUSH    DX
ENDM

PopAll        MACRO
    POP                DX
    POP                CX
    POP                BX
    POP                DI
    POP                SI
ENDM
start:
    MOV                AX,DATA
    MOV                DS,AX
    MOV                ES,AX

    XOR                AX,AX
    LEA                DI,count
    MOV                CX,256
@1:
    INC                DI
    STOSB
    INC                AX
    LOOP        @1

    LEA         DX,msg
    MOV         AH,9
    INT         21H
    CALL        InputChar
    CALL        Sort
    CALL        Output

    MOV                AX,4C00H
    INT                21H

Output        PROC
    EnterLine
    MOV                AH,9
    LEA                DX,msg1
    INT                21H
    PUSH        count4Number
    CALL        OutputByte
    EnterLine
    
    MOV                AH,9
    LEA                DX,msg2
    INT                21H
    PUSH        count4Uletter
    CALL        OutputByte
    EnterLine
    
    MOV                AH,9
    LEA                DX,msg3
    INT                21H
    PUSH        count4Lletter
    CALL        OutputByte
    EnterLine
    
    MOV                AH,9
    LEA                DX,msg4
    INT                21H
    PUSH        count4Other
    CALL        OutputByte
    EnterLine

    MOV                CX,256
    LEA                SI,count
    XOR                BX,BX

OutputLoop:
    LODSW
    TEST        AL,AL
    JE                OutEnd
    CMP                AL,BL
    JE                SameTimes

    MOV                BL,AL
    PUSH        AX
    EnterLine

    PUSH        BX
    CALL        OutputByte

    MOV                AH,9
    LEA                DX,msg5
    INT                21H
    POP                AX

    MOV                DL,AH
    MOV                AH,2
    INT                21H
    JMP                @@1
SameTimes:
    PUSH        AX
    MOV                AH,02
    MOV                DL,','
    INT                21H
    POP                AX
    MOV                DL,AH
    MOV                AH,2
    INT                21H
@@1:
    LOOP        OutputLoop
OutEnd:
    RET
Output        ENDP

InputChar        PROC
    LEA                DI,count
    LEA                SI,count4number
    XOR                CX,CX
@2:
    MOV                AH,1
    INT                21H
    CMP                AL,0DH
    JE                @3

    ;小于32大于等于127的字符放弃(32是空格,126是~)
    CMP                AL,32
    JL                @2
    CMP                AL,127
    JAE                @2
    
    ;判断数字
    CMP                AL,'0'
    JL                @4
    CMP                AL,'9'
    JG                @5
    ;是数字
    INC                BYTE PTR [SI]
    JMP                @7
@5:
    ;判断大写字母
    CMP                AL,'A'
    JL                @4
    CMP                AL,'Z'
    JG                @6
    ;是大写字母
    INC                BYTE PTR [SI+2]
    JMP                @7
@6:
    ;判断小写字母
    CMP                AL,'a'
    JL                @4
    CMP                AL,'z'
    JG                @4
    ;是小写字母
    INC                BYTE PTR [SI+4]
    JMP                @7
@4:
    ;是其他字符
    INC                BYTE PTR [SI+6]
@7:
    XOR                AH,AH
    SHL                AX,1
    MOV                BX,AX
    ;统计每个字符的出现次数
    INC                BYTE PTR [DI+BX]
    
    ;控制输入字符不超过255个
    INC                CX
    CMP                CX,255
    JGE                @3
    JMP                @2
@3:
    RET
InputChar        ENDP

;字符出现次数排序
Sort        PROC
    LEA                DI,count
    MOV                CX,256
outLoop:        
    PUSH        CX
    DEC                CX
    CMP                CX,1
    JE                SortOver
    MOV                BX,CX
innerLoop:
    PUSH        BX
    SUB                BX,CX
    SHL                BX,1
    MOV                AX,[DI+BX]
    CMP                AL,[DI+BX+2]
    JAE                BigThan
    PUSH        [DI+BX+2]
    POP                [DI+BX]
    PUSH        AX
    POP                [DI+BX+2]
BigThan:
    POP                BX
    LOOP        innerLoop
    POP                CX
    LOOP        outLoop
SortOver:
    POP                CX
    RET
Sort        ENDP

OutputByte        PROC
    PUSH        BP
    MOV                BP,SP
    SUB                SP,4
    PushAll

    MOV                WORD PTR [BP-2],0
    MOV                WORD PTR [BP-4],100

    MOV                CX,3
    MOV                AX,[BP+4]
OBLoop:
    XOR                DX,DX
    DIV                WORD PTR [BP-4]
    XCHG        AX,DX
    TEST        DX,DX
    JNE                OutputIt
    MOV                BX,[BP-2]
    TEST        BX,BX
    JE                NoOutput
OutputIt:
    PUSH        AX
    MOV                AH,02
    ADD                DL,030H
    INT                21H
    INC                WORD PTR [BP-2]
    POP                AX
NoOutput:
    PUSH        AX
    XOR                DX,DX
    MOV                AX,[BP-4]
    MOV                BX,10
    DIV                BX
    MOV                [BP-4],AX
    POP                AX
    LOOP        OBLoop

    MOV                AX,[BP-2]
    TEST        AX,AX
    JNE                OBEnd
    MOV                AH,2
    MOV                DL,'0'
    INT                21H
OBEnd:

    PopAll
    ADD                SP,4
    MOV                SP,BP
    POP                BP
    RET                2
OutputByte        ENDP

CODE        ENDS
END start